package com.zengge.zbc.service.impl;

import com.zengge.zbc.dto.Device;
import com.zengge.zbc.exception.ErrorCode;
import com.zengge.zbc.exception.ServiceException;
import com.zengge.zbc.mapper.DeviceInfoMapper;
import com.zengge.zbc.mapper.RoomInfoMapper;
import com.zengge.zbc.po.DeviceInfo;
import com.zengge.zbc.po.RoomInfo;
import com.zengge.zbc.service.DeviceService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;

@Service
public class DeviceServiceImpl implements DeviceService {

    private final DeviceInfoMapper deviceInfoMapper;
    private final RoomInfoMapper roomInfoMapper;

    @Autowired
    public DeviceServiceImpl(DeviceInfoMapper deviceInfoMapper,
                             RoomInfoMapper roomInfoMapper) {
        this.deviceInfoMapper = deviceInfoMapper;
        this.roomInfoMapper = roomInfoMapper;
    }

    private void checkRoomInfoPermission(List<RoomInfo> roomInfos, long roomId, long userId) {

        boolean permission = false;
        for (RoomInfo roomInfo : roomInfos) {
            if (roomInfo.getUserObjId() == userId && roomId == roomInfo.getObjectId()) {
                permission = true;
                break;
            }
        }
        if (!permission) {
            throw ServiceException.toError(ErrorCode.NOT_PERMISSION);
        }
    }

    public List<Long> getRoomId(List<RoomInfo> roomInfos) {
        List<Long> objectIds = new ArrayList<>(roomInfos.size());
        for (RoomInfo roomInfo : roomInfos) {
            objectIds.add(roomInfo.getObjectId());
        }
        return objectIds;
    }

    public int maxMacAddress(List<DeviceInfo> deviceInfos) {
        int maxAddress = 1;
        for (DeviceInfo deviceInfo : deviceInfos) {
            if (maxAddress < deviceInfo.getMacAddress()) {
                maxAddress = deviceInfo.getMacAddress();
            }
        }
        return maxAddress;
    }

    @Transactional
    @Override
    public String saveOrUpdateDevice(Device device, long userId) {

        String deviceId = device.getDeviceId();
        List<RoomInfo> roomInfos = roomInfoMapper.findRoomInfosByUserObjId(userId);
        checkRoomInfoPermission(roomInfos, Long.parseLong(device.getRoomId()), userId);

        if (deviceId != null) {
            DeviceInfo deviceInfo =
                    deviceInfoMapper.findDeviceInfoByObjectId(Long.parseLong(device.getDeviceId()));
            if (deviceInfo == null)
                throw ServiceException.toError(ErrorCode.DEVICE_NOT_FOUND);

            deviceInfo.setDeviceName(device.getDeviceName());
            deviceInfo.setDeviceType(device.getDeviceType());
            deviceInfo.setDeviceCct(Long.parseLong(device.getDeviceCct()));
            deviceInfo.setDeviceBrightness(Long.parseLong(device.getDeviceBrightness()));
            deviceInfoMapper.update(deviceInfo);
            return String.valueOf(deviceInfo.getObjectId());
        } else {

            List<Long> roomIds = getRoomId(roomInfos);
            List<DeviceInfo> deviceInfos = deviceInfoMapper.findDeviceInfoListByRoomObjIds(roomIds);
            int maxAddress = maxMacAddress(deviceInfos);
            DeviceInfo deviceInfo = new DeviceInfo(device.getDeviceName(), (maxAddress + 1),
                    Long.parseLong(device.getRoomId()),
                    Long.parseLong(device.getDeviceCct()),
                    Long.parseLong(device.getDeviceBrightness()),
                    device.getDeviceType(),
                    userId);

            deviceInfoMapper.save(deviceInfo);
            return String.valueOf(deviceInfo.getObjectId());
        }
    }


    private Device createDevice(DeviceInfo deviceInfo) {
        return new Device(String.valueOf(deviceInfo.getObjectId()),
                deviceInfo.getDeviceName(),
                deviceInfo.getMacAddress(),
                String.valueOf(deviceInfo.getRoomObjId()),
                String.valueOf(deviceInfo.getDeviceCct()),
                String.valueOf(deviceInfo.getDeviceBrightness()),
                String.valueOf(deviceInfo.getDeviceType()));
    }

    @Override
    public List<Device> deviceListGet(String roomId) {

        List<DeviceInfo> deviceInfos = deviceInfoMapper.findDeviceInfoListByRoomObjId(Long.parseLong(roomId));
        List<Device> devices = new ArrayList<>(deviceInfos.size());
        for (DeviceInfo deviceInfo : deviceInfos) {
            devices.add(createDevice(deviceInfo));
        }
        return devices;
    }

    @Override
    public Device deviceGet(String deviceId) {
        DeviceInfo deviceInfo = deviceInfoMapper.findDeviceInfoByObjectId(Long.parseLong(deviceId));
        if (deviceInfo == null)
            throw ServiceException.toError(ErrorCode.DEVICE_NOT_FOUND);
        return createDevice(deviceInfo);
    }

    @Transactional
    @Override
    public void deleteDevice(String deviceId) {
        DeviceInfo deviceInfo = deviceInfoMapper.findDeviceInfoByObjectId(Long.parseLong(deviceId));
        if (deviceInfo != null)
            deviceInfoMapper.delete(deviceInfo);
    }
}
